<!--
 * @Author: wei_jt@ecidi.com
 * @Date: 2019-09-17 16:44:32
 * @LastEditors: wei_jt@ecidi.com
 * @LastEditTime: 2021-12-27 21:53:29
 * @Description: 菜单配置
 -->
<template>
  <div class="main-wrapper drawer-container">
    <div class="line-button">
      <div class="page-button">
        <div class="page-title" style="display: flex">
          <div class="fks-title-icon" />
          <span style="font-weight: bold; font-size: 16px; color: #191919">{{
            LANG.MENU_MANAGEMENT
          }}</span>
        </div>
        <div>
          <fks-select
            v-if="multiPortal"
            v-model="radio"
            size="medium"
            style="width: auto"
          >
            <fks-option
              v-for="type in portalTypes"
              :key="type.code"
              :label="type[$lang]"
              :value="type.code"
            />
          </fks-select>
          <fks-input
            v-model="keywords"
            size
            style="width: auto; margin-left: 8px"
            :placeholder="LANG.INPUT_ROUTENAME_OR_ROUTEPATH"
            clearable
            maxlength="50"
            @keyup.native.enter="getMenuTree"
            @clear="getMenuTree"
          >
            <fks-button
              slot="append"
              icon="fks-icon-search"
              @click="getMenuTree"
            />
          </fks-input>
          <fks-button style="margin-left: 8px" @click="show = !show">
            <fks-checkbox
              v-model="show"
              style="font-size: 0; vertical-align: bottom"
              @click.native.stop
            />
            <span style="margin-left: 8px">{{ LANG.NOT_HIDDEN }}</span>
          </fks-button>
          <fks-button style="margin-left: 8px" @click="importData">
            <i class="fks-icon-import" />
            <span style="margin-left: 8px">{{ LANG.IMPORT }}</span>
          </fks-button>
          <fks-button style="margin-left: 8px" @click="exportData">
            <i class="fks-icon-export" />
            <span style="margin-left: 8px">{{ LANG.EXPORT }}</span>
          </fks-button>
          <fks-button
            v-permission:1="['menu:add']"
            type="primary"
            style="margin-left: 8px"
            icon="fks-icon-plus"
            @click="addRootNode"
          >
            {{ LANG.ADD }}
          </fks-button>
        </div>
      </div>
    </div>
    <fks-table
      ref="tree"
      v-loading="loading"
      class="menu-table"
      :data="treeData"
      row-key="id"
      height="calc(100% - 65px)"
      @row-click="rowClick"
      @select="handleSelection"
      @selection-change="handleSelectionChange"
      @select-all="handleSeletionAll"
    >
      <fks-table-column type="selection" width="55" />
      <fks-table-column
        :label="LANG.NAME"
        prop="title"
        width="400px"
        header-align="center"
        align="left"
      >
        <template slot-scope="scope">
          {{ LANG[scope.row.content.title] || scope.row.content.title }}
        </template>
      </fks-table-column>
      <fks-table-column
        :label="LANG.ROUTEPATH"
        prop="content.path"
        width="300px"
        header-align="center"
        align="left"
      />
      <fks-table-column :label="LANG.ICON" prop="icon" align="center">
        <template slot-scope="scope">
          <fks-icon
            v-if="scope.row.content.icon"
            :icon-class="scope.row.content.icon"
          />
        </template>
      </fks-table-column>
      <fks-table-column
        prop="enable"
        align="center"
        header-align="center"
        min-width="100"
      >
        <template slot="header">
          {{ LANG.ACTIVATE }}
        </template>
        <template slot-scope="scope">
          <div @click.stop.prevent>
            <fks-switch
              v-model="scope.row.content.enable"
              :active-value="true"
              :inactive-value="false"
              @change="change(scope.row)"
            />
          </div>
        </template>
      </fks-table-column>
      <fks-table-column :label="LANG.IS_AUTH" prop="auth" align="center">
        <template slot-scope="scope">
          <div @click.stop.prevent>
            <fks-switch
              v-model="scope.row.content.isAuth"
              :active-value="true"
              :inactive-value="false"
              @change="change(scope.row)"
            />
          </div>
        </template>
      </fks-table-column>
      <fks-table-column :label="LANG.SORT" prop="content.sort" align="center" />
      <fks-table-column :label="LANG.OPERATION" width="200" align="left">
        <template slot-scope="scope">
          <fks-button
            v-permission:1="['menu:edit']"
            type="text"
            @click.stop="edit(scope.row.content)"
          >
            {{ LANG.EDIT }}
          </fks-button>
          <fks-button
            v-permission:1="['menu:add']"
            type="text"
            @click.stop="addSubMenu(scope.row.content)"
          >
            {{ LANG.ADD_CHILD }}
          </fks-button>
          <fks-button
            v-permission:1="['menu:delete']"
            danger-text
            @click.stop="handleDelete(scope.row.content.id)"
          >
            {{ LANG.DELETE }}
          </fks-button>
        </template>
      </fks-table-column>
    </fks-table>
    <menu-detail
      v-if="visible"
      :data="node"
      :visible.sync="visible"
      @reset="reset"
    />
    <fks-dialog
      width="960px"
      class="export-dialog"
      :title="title"
      :visible.sync="exportVisible"
      @close="close"
    >
      <div slot="title">
        <i
          v-if="this.operate == 'import'"
          v-permission:1="['menu:import']"
          class="fks-icon-import"
        />
        <i
          v-if="this.operate == 'export'"
          v-permission:1="['menu:export']"
          class="fks-icon-export"
        />
        {{ this.title }}
      </div>
      <div class="main">
        <fks-form ref="form" label-width="0px">
          <fks-form-item v-if="operate == 'export'" :span="24">
            <span style="font-size: 16px">{{ LANG.CONFIRM_MENU }}</span>
          </fks-form-item>
          <fks-form-item v-if="operate == 'export'">
            <template>
              <fks-table
                :data="exportMenu"
                row-key="id"
                heigth="500px"
                default-expand-all
              >
                <fks-table-column
                  :label="LANG.NAME"
                  prop="title"
                  header-align="center"
                  width="350"
                  align="left"
                  size="mini"
                >
                  <template slot-scope="scope">
                    {{ LANG[scope.row.title] || scope.row.title }}
                  </template>
                </fks-table-column>
                <fks-table-column
                  :label="LANG.ROUTEPATH"
                  prop="path"
                  header-align="center"
                  width="350"
                  align="left"
                />
                <fks-table-column :label="LANG.ICON" prop="icon" align="center">
                  <template slot-scope="scope">
                    <fks-icon
                      v-if="scope.row.icon"
                      :icon-class="scope.row.icon"
                    />
                  </template>
                </fks-table-column>
                <fks-table-column
                  :label="LANG.SORT"
                  prop="content.sort"
                  align="center"
                />
              </fks-table>
            </template>
          </fks-form-item>
          <fks-form-item v-if="operate == 'import'" :span="24">
            <span v-if="exportMenu.length == 0" style="font-size: 16px">{{
              LANG.DEFAULT_MENU_TIPS
            }}</span>
            <span v-if="exportMenu.length == 1" style="font-size: 16px">
              {{ LANG.CONFIRM_MENU_TIPS }}</span
            >
            <span v-if="exportMenu.length == 1" style="font-size: 16px">
              {{ LANG.CHECKED_TIP }}
              {{ LANG[exportMenu[0].title] || exportMenu[0].title }}
            </span>
          </fks-form-item>
          <fks-form-item
            v-if="operate == 'import' && exportMenu.length <= 1"
            :span="24"
          >
            <span style="font-size: 16px">{{ LANG.UPLOAD_TIP }}</span>
          </fks-form-item>
          <fks-form-item
            v-if="operate == 'import' && exportMenu.length <= 1"
            :span="24"
          >
            <fks-upload
              ref="upload"
              class="menu-upload"
              :action="uploadUrl"
              drag
              name="file"
              :headers="{
                'Fawkes-Auth': ACESS_TOKEN
              }"
              :with-credentials="true"
              :auto-upload="false"
              :limit="1"
              accept=".json_"
              :file-list="fileList"
              :http-request="importMenu"
            >
              <i class="fks-icon-upload" />
              <div class="fks-upload__text">
                {{ LANG.FILE_UPLOAD_TIPS }}
                <em>{{ LANG.COMFIRM_UPLOAD }}</em>
                <br />
                <span>{{ LANG.FILE_FORMAT }}</span>
              </div>
            </fks-upload>
          </fks-form-item>
        </fks-form>
      </div>
      <div slot="footer">
        <fks-button
          v-if="operate == 'export'"
          type="primary"
          icon="fks-icon-check"
          @click="exportMenuData"
        >
          {{ LANG.EXPORT }}
        </fks-button>
        <fks-button
          v-if="operate == 'import'"
          type="primary"
          icon="fks-icon-check"
          :disabled="exportMenu.length > 1"
          @click="importDone"
        >
          {{ LANG.IMPORT }}
        </fks-button>
      </div>
    </fks-dialog>
  </div>
</template>
<script>
import * as Auth from './api'
import MenuDetail from './MenuDetail'
import * as types from '@/store/Getter/getterTypes.js'
import Mix from '@/mixins/module'
import { arrayToTree } from '@/utils/array'
import { exportFile } from '@/utils/file'
export default {
  name: 'Menu',
  components: {
    MenuDetail
  },
  filters: {
    /**
     * @description: 超过多少字省略
     * @param {type}
     * @return:
     */
    ellipsis(value, node) {
      let num = 16 - (node.level - 1) * 2
      if (node.isLeaf) {
        num++
      }
      if (value && value.length > num) {
        return value.substring(0, num - 2) + '...'
      } else {
        return value
      }
    }
  },
  mixins: [Mix],
  data() {
    return {
      defaultProps: {
        children: 'children',
        label: 'name'
      },
      keywords: '',
      node: {},
      visible: false,
      showNode: true,
      loading: false,
      treeList: [],
      radio: '',
      show: true,
      auth: '',
      ACESS_TOKEN: this.$storage.get('access_token'),
      uploadUrl: '',
      operate: '',
      importPortalType: '',
      exportVisible: false,
      exportMenu: [],
      fileList: []
    }
  },
  computed: {
    /* state中取门户类型 */
    portalTypes() {
      return this.$store.state.enum.portalType || []
    },
    portal() {
      return this.$store.state.portal
    },
    /* state中取多门户开关是否开启 */
    multiPortal() {
      return this.$store.getters.multiPortal
    },
    title() {
      switch (this.operate) {
        case 'export':
          return this.LANG.EXPORT_CONFIG
        default:
          return this.LANG.IMPORT_CONFIG
      }
    },
    treeData() {
      let origin = JSON.parse(JSON.stringify(this.treeList))
      return this.filterTable(origin, this.keywords) || []
    }
  },
  watch: {
    portal: {
      immediate: true,
      handler: function () {
        if (this.$store.getters.multiPortal) {
          this.radio = /^\d+$/.test(this.$storage.get('auth_portal'))
            ? this.$storage.get('auth_portal')
            : this.portal.type
            ? this.portal.type + ''
            : ''
        }
      }
    },
    radio: {
      immediate: true,
      handler: function () {
        this.importPortalType = this.radio
        this.$storage.set('auth_portal', this.radio)
        this.getMenuTree()
      }
    }
  },
  beforeDestroy() {
    this.treeList = []
  },
  methods: {
    /**
     * @description: 编辑按钮弹窗关闭时，恢复树的可收缩伸展
     * @param {Boolean}
     * @return:
     */
    reset(params) {
      this.showNode = params
    },
    /**
     * @description: 获取菜单树
     * @param {type}
     * @return:
     */
    @permission('menu:query')
    getMenuTree() {
      this.visible = false
      this.loading = true
      return new Promise((resolve) => {
        let params = {
          type: this.$storage.get('auth_portal') || this.radio
        }
        Auth.getMenusTree(params)
          .then((res) => {
            if (res.status) {
              this.treeList = [...res.data]
            } else {
              this.treeList = []
            }
            this.loading = false
            resolve(true)
          })
          .catch(() => {
            this.treeList = []
            this.loading = false
            resolve(true)
          })
      })
    },
    //点击表格回调
    rowClick(row) {
      if (!row.children) {
        if (this.$refs.tree.selection.includes(row)) {
          this.$refs.tree.toggleRowSelection(row, false)
        } else {
          this.$refs.tree.toggleRowSelection(row, true)
        }
        return
      }
      if (this.$refs.tree.selection.includes(row)) {
        this.$refs.tree.toggleRowSelection(row, false)
        this.checkRow(row.children, false)
      } else {
        this.$refs.tree.toggleRowSelection(row, true)
        this.checkRow(row.children, true)
      }
    },
    edit(data) {
      //点击编辑时 树不收缩伸展
      this.showNode = false
      this.node = Object.assign({}, data)
      this.node.operate = 'edit'
      this.visible = true
    },

    /**
     * @description: 删除菜单
     * @param {id}
     * @return:
     */
    handleDelete(id) {
      this.$confirm(this.LANG.CONFIRM_TIPS, this.LANG.TIPS, {
        type: 'warning',
        confirmButtonText: this.LANG.DELETE,
        cancelButtonText: this.LANG.CANCEL,
        confirmButtonClass: 'fks-button--danger',
        deleteMode: true
      })
        .then(() => {
          Auth.deleteMenu(id).then((res) => {
            if (res.status) {
              this.$message.success(this.LANG.DELETE_SUCCESS)
              this.getMenuTree()
            }
          })
        })
        .catch(() => {})
    },

    /**
     * @description: 新增子菜单节点-打开弹窗
     * @param {val}
     * @return:
     */
    addSubMenu(val) {
      this.node = { pathId: val.pathId, parentId: val.id, operate: 'add' }
      this.visible = true
    },
    /**
     * @description: 新增根菜单节点-打开弹窗
     * @param {}
     * @return:
     */
    addRootNode() {
      this.node = { parentId: '', operate: 'add', icon: '' }
      this.visible = true
    },
    //选中菜单
    handleSelection(select, row) {
      if (!row.children) {
        return false
      }
      if (this.$refs.tree.selection.includes(row)) {
        this.checkRow(row.children, true)
      } else {
        this.checkRow(row.children, false)
      }
    },
    //选择改变
    handleSelectionChange() {
      let data = []
      this.$refs.tree.selection.forEach((item) => {
        let val = {}
        val = item.content
        if (item.children) {
          val.children = item.children
        }
        data.push(val)
      })
      let treeData = arrayToTree(data, 'parentId', '0')
      this.exportMenu = treeData
    },

    //全选
    handleSeletionAll(select) {
      this.$refs.tree.clearSelection()
      this.checkRow(select, true)
    },

    //选中递归
    checkRow(data, bool) {
      data.forEach((item) => {
        this.$refs.tree.toggleRowSelection(item, bool)
        if (item.children) {
          this.checkRow(item.children, bool)
        }
      })
    },

    //过滤树形数据
    filterTable(list, val) {
      return list.filter((item) => {
        if (!this.show && !item.content.enable) {
          return false
        }
        if (item.children) {
          let arr = this.filterTable(item.children, val)
          item.children = arr
          if (arr instanceof Array && arr.length > 0) {
            return true
          }
        }

        if (!item.content.title) {
          return false
        }

        if (
          this.LANG[item.content.title] &&
          this.LANG[item.content.title].indexOf(val) != -1
        ) {
          return true
        }

        if (item.content.title.indexOf(val) != -1) {
          //满足未配置多语言的情况
          return true
        }
        return false
      })
    },

    /**
     * @description: 列表中编辑菜单
     * @param {val}
     * @return:
     */
    change(row) {
      Auth.saveMenu(row.content).then((res) => {
        if (res.status) {
          this.getMenuTree()
          this.$message({
            message: this.LANG.UPDATE_SUCCESS,
            type: 'success',
            duration: 3000
          })
        }
      })
    },

    //导出
    exportData() {
      if (!this.exportMenu || !this.exportMenu.length) {
        this.$message({
          message: this.LANG.EXPORT_TIPS,
          type: 'warning'
        })
        return false
      }
      this.operate = 'export'
      this.exportVisible = true
    },

    //  关闭导入导出弹窗
    close() {
      this.exportVisible = false
      this.fileList = []
    },

    //导出数据
    exportMenuData() {
      Auth.exportMenu(this.exportMenu).then((res) => {
        if (res.status) {
          this.$message.success(this.LANG.EXPORT_SUCCESS)
          exportFile(res)
          this.$refs.tree.clearSelection()
          this.exportMenu = []
          this.close()
        } else {
          this.$message.error(this.LANG.EXPORT_ERROR)
        }
      })
    },

    //打开导入菜单弹窗
    importData() {
      if (this.exportMenu.length > 1) {
        this.$message.error(this.LANG.CONFIRM_MENU_ERROR)
      } else {
        this.operate = 'import'
        this.exportVisible = true
      }
    },

    //上传导入文件
    importMenu(params) {
      let menu = {}
      if (this.exportMenu.length == 0) {
        menu.id = '0'
      } else {
        menu = this.exportMenu[0]
      }
      let form = new FormData()
      //文件对象
      form.append('parentId', menu.id)
      form.append('type', this.importPortalType)
      form.append('file', params.file)
      Auth.importMenu(form).then((res) => {
        if (res.status) {
          this.$message.success(this.LANG.SUCCESS)
          this.getMenuTree()
        }
      })
    },

    //导入菜单文件
    importDone() {
      this.$refs.upload.submit()
      this.close()
    }
  }
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.drawer-container {
  box-sizing: border-box;
  width: 100%;
  min-width: 1044px;
  height: 100%;
  padding: 24px 32px;
  overflow-y: auto;
  background-color: white !important;

  .page-button {
    display: flex;
    justify-content: space-between;
  }
}

.line-button {
  margin-bottom: 24px;
}

.menu-table {
  width: 100%;
}

.menu-upload {
  width: auto;
}

::v-deep .fks-upload-dragger {
  width: 895px;
}
</style>
